k8s 自定义controller
k8s 自定义controller
CRD Controller的开发逻辑
控制器的目的是让 CRD 定义的资源达到我们预期的一个状态,要达到我们定义的状态,我们需要监听触发事件。触发事件的概念是从硬件信号产生 中断
的机制衍生过来的,
其产生一个电平信号时,有水平触发(包括高电平、低电平),也有边缘触发(包括上升沿、下降沿触发等)。
- 水平触发 : 系统仅依赖于当前状态。即使系统错过了某个事件(可能因为故障挂掉了),当它恢复时,依然可以通过查看信号的当前状态来做出正确的响应。
- 边缘触发 : 系统不仅依赖于当前状态,还依赖于过去的状态。如果系统错过了某个事件(“边缘”),则必须重新查看该事件才能恢复系统。
Kubernetes 的 API 和控制器都是基于水平触发的,可以促进系统的自我修复和周期调协。
其 API 实现方式(也是我们常说的声明式 API)是:控制器监视资源对象的实际状态,并与对象期望的状态进行对比,然后调整实际状态,使之与期望状态相匹配。
那 KubeBuilder 原理呢?
它的控制器实现的接口是 Reconcile 方法,该方法要求控制器的实现逻辑是基于水平触发的, 实现方不能假定每一次的对象的变更都会触发一次 Reconcile。KubeBuilder 为性能考虑会合并同一个对象的修改请求,这要求使用方不考虑中间的执行步骤,以面向终态的方式来实现业务逻辑。具体来说每次资源 Status 状态的构建都不能依赖过去的值,要求能够完全根据目前的环境的查询来构建值。
CRD Controller 开发环境搭建
我们创建了CRD,再通过自动生成代码的工具将controller所需的informer、client等依赖全部准备好,到了本章,就该编写controller的代码了,也就是说,现在已经能监听到Student对象的增删改等事件,接下来就是根据这些事件来做不同的事情,满足个性化的业务需求;
controller的作用就是监听指定对象的新增、删除、修改等变化,针对这些变化做出相应的响应(例如新增pod的响应为创建docker容器),关于controller的详细设计,最好的参考就是Harry (Lei) Zhang老师在twitter上的分享,如下图,地址是:https://twitter.com/resouer/status/1009996649832185856
原理:
如上图,API对象的变化会通过Informer存入队列(WorkQueue),在Controller中消费队列的数据做出响应,响应相关的具体代码就是我们要做的真正业务逻辑;
https://book.kubebuilder.io/introduction.html
使用 KubeBuilder v2 版本,该框架可以方便的生成符合 K8S 规范的 CRD 文件和对应的 Controller 代码,我们只需要实现其调协逻辑即可。
安装kubeBuilder
安装kubeBuilder的必要条件:
- go version v1.13+.
- docker version 17.03+.
- kubectl version v1.11.3+.
- Access to a Kubernetes v1.11.3+ cluster.
我使用的是mac os,当前的go版本是v1.12,需要升级,由于升级太麻烦了,我之前是通过homebrew安装的,所以我直接卸载掉,从官网上下载最新的go版本,直接安装:
现在已经满足了安装kubebuilder的要求了。
官方文档是这样安装的:
os=$(go env GOOS)
arch=$(go env GOARCH)
# download kubebuilder and extract it to tmp
curl -L https://go.kubebuilder.io/dl/2.3.1/${os}/${arch} | tar -xz -C /tmp/
# move to a long-term location and put it on your path
# (you'll need to set the KUBEBUILDER_ASSETS env var if you put it somewhere else)
sudo mv /tmp/kubebuilder_2.3.1_${os}_${arch} /usr/local/kubebuilder
export PATH=$PATH:/usr/local/kubebuilder/bin
但我电脑上好像无法这样安装,只能通过这样安装:
os=$(go env GOOS)
arch=$(go env GOARCH)
wget https://go.kubebuilder.io/dl/latest/${os}/${arch}
tar -xzvf kubebuilder_master_darwin_amd64.tar.gz -C /tmp/
sudo mv /tmp/kubebuilder_master_darwin_amd64 /usr/local/kubebuilder
export PATH=$PATH:/usr/local/kubebuilder/bin
使环境变量永久生效,加入到.bash_profile, vi ~/.bash_profile
:
export PATH=$PATH:/usr/local/kubebuilder/bin
source ~/.bash_profile
检查kubebuilder是否安装成功:
发现已经安装成功了!!!
使用kubebuilder生成controller+crd模板
kubebuilder官网生成controller模板:
https://github.com/kubernetes-sigs/kubebuilder
生成架构代码
有两种方法,一种是采用 GOPATH
,另一种是 go mod
官方建议:
If you’re not in
GOPATH
, you’ll need to rungo mod init <modulename>
in order to tell kubebuilder and Go the base import path of your module.
我电脑上也没配置GOPATH,所以我只能通过go mod 方式。
一般不建议通过在GOPATH目录下新建项目,所以我使用go mod
方式生成架构代码:
因为墙的原因,需要设置go的代理:export GOPROXY=https://goproxy.cn
,否则kubebuilder init时会timeout
mkdir test1 && go mod init my.domain
返回:
go: creating new go.mod: module my.domain
kubebuilder init –domain my.domain
返回如下信息:
初始化项目完成!!
现在我们只生成了第一步的代码,我们先来看看这部分代码是否能运行及其效果如何?
这时需要保证你的终端能访问 K8S 的测试集群,简单就是用 kubectl cluster-info
看看是否出错,如果不出错,就可以 go run main.go
了
由以上图片可以看出,集群是正常运行的。
现在我们执行一下 go run main.go
返回:
从以上图片返回的结果可以看出,其实 KubeBuilder 帮我们生成一个管理 Controller 的 Manager 的代码(controller-runtime.manager),但是还没添加 Controller
创建CRD
创建一个名为Guestbook的CRD, 路径为webapp/v1:
kubebuilder create api --group webapp --version v1 --kind Guestbook
执行后报错了:
是不是由于我安装的kubeBuilder版本是master版本,对应的k8s版本是1.16.4的原因?
经过不断的探索,发现是由于我k8s的api server所支持的go版本是v1.13.5:
将最新的1.16版本卸载,安装1.13.5这个版本
再次执行:
kubebuilder create api --group webapp --version v1 --kind Guestbook
返回成功:
这里简单注意一下, group / version / kind
这三个属性组合起来来标识一个 K8S 的 CRD。另外就是 kind
要首字母大写而且不能有特殊符号
成功建立了一个自定义crd了,但是内容是空的,没做任何事。。。。
安装CRD到集群
make install
又报错了:
是因为没有安装kustomize,那我安装一个:
bwi kustomize
再次执行,返回成功:
查看一下,是否安装成功:
此时已经将 CRD 安装到集群了。
启动控制器
使用make run 命令启动控制器: